package com.message.api.user.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.base.annotation.SysLog;
import com.base.annotation.Unsecured;
import com.base.context.Context;
import com.base.context.ContextHolder;
import com.base.helper.BaseController;
import com.base.helper.PwdCheckUtil;
import com.base.helper.Result;
import com.base.helper.StringUtils;
import com.base.interceptor.ContextInjectInterceptor;
import com.message.api.group.entity.AcGroup;
import com.message.api.group.service.AcActionPageService;
import com.message.api.group.service.AcGroupService;
import com.message.api.user.entity.AcUser;
import com.message.api.user.service.AcLoginlogService;
import com.message.api.user.service.AcUserService;
import com.message.api.user.vo.*;
import com.message.config.UserConfig;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author mzl
 * @since 2020-07-09
 */
@Api(tags = "用户")
@RestController
@RequestMapping("/acUser")
public class AcUserController extends BaseController {

    private static final Logger              LOG = LoggerFactory.getLogger(AcUserController.class);
    @Autowired
    private              AcUserService       entityService;
    @Autowired
    private              AcGroupService      acGroupService;
    @Autowired
    private              AcActionPageService acActionPageService;
    @Autowired
    private              UserConfig          userConfig;
    @Autowired
    private              AcLoginlogService   acLoginlogService;

    @SysLog(action = "acUser:findByPage", value = "用户管理：用户列表")
    @ApiOperation(value = "分页查询用户", notes = "分页查询用户")
    @RequestMapping(method = RequestMethod.GET)
    @ApiImplicitParams({@ApiImplicitParam(name = "size", value = "分页大小", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页面：从1开始", paramType = "query")})
    public Result<IPage<AcUserVo>> findByPage(final AcUserVo example, final Page page) {
        IPage<AcUserVo> records = entityService.findByPage(page, example);
        return new Result(true, records);
    }

    @SysLog(action = "acUser:delete", value = "用户管理：删除用户")
    @ApiOperation(value = "删除用户")
    @RequestMapping(value = "{id}", method = {RequestMethod.DELETE})
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path")
    public Result delete(@PathVariable final Integer id) {
        AcUser acUser = entityService.getById(id);
        if (null == acUser) {
            throw new RuntimeException("没有找到Id对应对象");
        }
        acUser.setState("0");
        entityService.updateById(acUser);
        return new Result(true, "成功删除用户", null);
    }

    @SysLog(action = "acUser:one", value = "用户管理：查询用户详细")
    @ApiOperation(value = "查询单个用户")
    @RequestMapping(value = "{id}", method = {RequestMethod.GET})
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path")
    public Result one(@PathVariable final Integer id) {
        AcUser entity = entityService.getById(id);
        return new Result(true, entity);
    }

    @SysLog(action = "acUser:add", value = "用户管理：添加用户")
    @ApiOperation(value = "添加用户")
    @RequestMapping(method = {RequestMethod.POST})
    public Result add(@Valid @RequestBody final AcUser entity) {
        AcUser acUser=entityService.lambdaQuery()
                .eq(AcUser::getUsername,entity.getUsername())
                .eq(AcUser::getState,"1").one();
        if(acUser!=null){
            return new Result(false, "添加失败，该账号已存在！", null);
        }
        if (null == entity.getId()) {
            entity.setState("1");
            entity.setEnable("1");
            entity.setCreatetime(new Date());
            entity.setTeacherNumber(entity.getUsername());
            entity.setPwdupdatetime(new Date());
            entity.setPassword("SnY@748THs");
            entity.setUsertype(1);
            entity.setEdit("2");
        }
        entityService.save(entity);
        return new Result(true, "成功保存用户", null);
    }

    @SysLog(action = "acUser:update", value = "用户管理：修改用户")
    @ApiOperation(value = "修改用户")
    @RequestMapping(method = {RequestMethod.PUT})
    public Result update(@Valid @RequestBody final AcUser entity) {
        if (null == entity.getId()) {
            throw new RuntimeException("id不能为空");
        }
        entityService.updateById(entity);
        return new Result(true, "成功修改用户", null);
    }

    @SysLog(action = "acUser:all", value = "用户管理：全部用户")
    @ApiOperation(value = "全部用户")
    @RequestMapping(value = "all", method = RequestMethod.GET)
    public Result<List<AcUserVo>> all(AcUserVo example) {
        List<AcUserVo> entitys = entityService.findByExample(example);
        if (null != entitys) {
            return new Result<>(true, entitys);
        }
        return new Result<>(true, Collections.emptyList());
    }

    @SysLog(action = "acUser:login", value = "用户管理：【用户】登录")
    @ApiOperation(value = "【用户】登录")
    @RequestMapping(value = "login", method = RequestMethod.POST)
    @Unsecured
    public Result<LoginSuccessVo> login(@Valid @RequestBody final LoginVo login) {
        Context context = ContextHolder.currentContext();
        Boolean toLogin = acLoginlogService.toLogin(login.getUsername());
        if (!toLogin) {
            return new Result(false, "登录失败", "登录失败次数超过5次，请半个小时后再进行尝试");
        }
        AcUser user = entityService.findByUsername(login.getUsername());
        if (null == user) {
            acLoginlogService.addLog(null, login.getUsername(), "f", "该账号不存在");
            return new Result(false, "该账号不存在", "该账号不存在");
        }
        if (!user.getUsertype().equals(login.getUsertype())) {
            return new Result(false, "账号或密码不正确", "账号或密码不正确");
        }
        if (StringUtils.isEquals(login.getPassword(), user.getPassword(), true)) {
            Long pwdUpdateSecond = (System.currentTimeMillis() - user.getPwdupdatetime().getTime()) / 1000;
            //密码到期时间小于10天，进行提醒，并强制修改
            Boolean updatepwd = (userConfig.getUpdatepwdtime() - pwdUpdateSecond) < 10 * 24 * 60 * 60;
            if ("1".equals(user.getEnable())) {
                acLoginlogService.addLog(user.getId(), login.getUsername(), "t", null);
                return new Result<>(true, normalizeContext(context, user));
            } else {
                acLoginlogService.addLog(user.getId(), login.getUsername(), "f", "账号被停用");
                return new Result(false, "登录失败", "用户已被停用，可联系管理员解封");
            }
        } else {
            acLoginlogService.addLog(user.getId(), login.getUsername(), "f", "账号或密码不正确");
            ContextHolder.remove(context.currentToken());
            return new Result(false, "账号或密码不正确", "账号或密码不正确");
        }

    }

    private LoginSuccessVo normalizeContext(Context context, AcUser user) {
        AcGroup  acGroup = acGroupService.getById(user.getAcgroup());
        AcUserVo vo      = new AcUserVo(user, acGroup.getGrouptypeid() + "", acGroup.getAcgroup());
        Context  ctx     = ContextHolder.isOnline(vo, AcUserVo.class);
        if (null != ctx && !StringUtils.isEquals(ctx.currentToken(), context.currentToken())) {
            ContextHolder.remove(ctx.currentToken());
        }
        context.asUser(vo);
        List<String> accessUris = acActionPageService.findByGroupid(acGroup.getId());
        if (null != accessUris && accessUris.size() > 0) {
            context.asAccessUris(accessUris);
        }
        user.setPassword(null);
        return new LoginSuccessVo(user, context.currentToken());
    }

    @SysLog(action = "acUser:logout", value = "用户管理：【用户】注销")
    @ApiOperation(value = "【用户】注销")
    @RequestMapping(value = "logout", method = GET)
    public Result logout(HttpServletResponse response) {
        Context context = ContextHolder.currentContext();
        ContextHolder.remove(context.currentToken());
        String token  = context.currentToken();
        Cookie cookie = new Cookie(ContextInjectInterceptor.TOKEN, token);
        cookie.setPath("/");
        cookie.setMaxAge(0);
        // 写回cookie
        response.addCookie(cookie);
        //
        if (LOG.isDebugEnabled()) {
            LOG.debug("token[{}]写回cookie", token);
        }
        return new Result(true, "退出成功", null);
    }

    @SysLog(action = "acUser:resetPwd", value = "用户管理：修改密码")
    @ApiOperation(value = "修改密码")
    @RequestMapping(value = "{id}/pwdreset", method = POST)
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "用户id", required = true, paramType = "path")})
    public Result resetPwd(@PathVariable("id") Integer id, @Valid @RequestBody final ResetPwdVo pwdVo,
                           final BindingResult result) {
        AcUser user = entityService.getById(id);
        if (null != user && StringUtils.isEquals(pwdVo.getOld(), user.getPassword(), true)) {
            user.setPassword(pwdVo.getPwd());
            entityService.updateById(user);
            return Result.SUCCESS;
        } else {
            return new Result(false, "修改密码失败", "请输入正确的旧密码");
        }
    }

    @SysLog(action = "acUser:pwdCheck", value = "用户管理:校验密码")
    @ApiOperation(value = "校验密码")
    @RequestMapping(value = "/pwdCheck", method = {RequestMethod.POST})
    public Result pwdCheck(@Valid @RequestBody final AcCheckPwdVo acCheckPwdVo) {
        return new PwdCheckUtil().checkPassword(acCheckPwdVo.getPwd());
    }

    @SysLog(action = "acUser:setStatus", value = "用户管理：设置用户状态")
    @ApiOperation(value = "设置用户状态")
    @RequestMapping(value = "{id}/set/{enable}", method = {RequestMethod.POST})
    @ApiImplicitParams({@ApiImplicitParam(name = "enable", value = "用户状态：1启用，0禁用", required = true, paramType = "path"
    )})
    public Result<AcUser> setStatus(@PathVariable(name = "id") final Integer id,
                                    @PathVariable(name = "enable") String enable) {
        Context context = ContextHolder.currentContext();
        if ("1".equals(enable) || "0".equals(enable)) {
            AcUser acUser = entityService.setEnable(id, enable);
            return new Result<>(true, acUser);
        } else {
            return new Result<>(true, "设置用户状态失败", "设置参数非法，只能设置为0或1");
        }
    }

    @Unsecured
    @SysLog(action = "acUser:setPwd", value = "用户管理：考生设置密码")
    @ApiOperation(value = "考生设置密码")
    @RequestMapping(value = "setPwd", method = POST)
    public Result resetPwd(@Valid @RequestBody final EnSetPwdVo setPwd) {
        entityService.setPwd(setPwd);
        return Result.SUCCESS;

    }

}

